package site.ruolin.Encrypt;

import site.ruolin.KeyGen.Key.PublicKey;

import java.math.BigInteger;
import java.security.SecureRandom;

/**
 * 加密
 * @author ruolin on 2025/09/11
 */
public class Encrypt {
    private final PublicKey publicKey;
    private final SecureRandom random;
    
    /**
     * 构造函数
     * @param publicKey 公钥
     */
    public Encrypt(PublicKey publicKey) {
        this.publicKey = publicKey;
        this.random = new SecureRandom();
    }
    
    /**
     * 加密
     * @param plainText 明文
     * @return 密文
     */
    public BigInteger encrypt(BigInteger plainText) { 
        // 检查明文是否在有效范围内
        if (plainText.compareTo(BigInteger.ZERO) < 0 ||
                plainText.compareTo(publicKey.getN()) >= 0) {
            throw new IllegalArgumentException("明文必须在 [0, n-1] 范围内");
        }
        
        // 选择随机数 r ∈ Z*n
        BigInteger r;
        do {
            r = new BigInteger(publicKey.getN().bitLength(), random);
        } while (r.compareTo(publicKey.getN()) >= 0 ||
                r.gcd(publicKey.getN()).compareTo(BigInteger.ONE) != 0);
        
        // 计算密文 c = g^m * r^n mod n^2
        BigInteger gm = publicKey.getG().modPow(plainText, publicKey.getNSquare());
        BigInteger rn = r.modPow(publicKey.getN(), publicKey.getNSquare());

        return gm.multiply(rn).mod(publicKey.getNSquare());
    }
    
}
